package com.enlorenz.common.geo.map.google;

import java.util.ArrayList;
import java.util.List;

import com.enlorenz.common.geo.map.base.FileWrapper;
import com.enlorenz.common.geo.map.base.ITileFilePathCreator;
import com.enlorenz.common.geo.map.base.MapConfig;
import com.enlorenz.common.geo.map.base.TileWrapper;
import com.enlorenz.common.geo.map.base.TileWrapperMessage;
import com.enlorenz.common.geo.map.google.GoogleTileParser.GoogleTileHooker;
import com.enlorenz.core.base.IMessage;
import com.enlorenz.core.engine.imp.thread.quick.AbstractQuickSleepFirstThread;
import com.enlorenz.core.queue.proc.AbstractObjectCycleThread;
import com.enlorenz.core.queue.transfer.imp.WaitMessageQueue;
import com.enlorenz.util.TimeUtil;

/**
 * Google瓦片文件解析
 * @author Karma
 *
 */
public class GoogleTileFileParser {
	private MapConfig mapConfig;
	//数据源文件创建者
	private ITileFilePathCreator srcCreator;
	//目标数据创建者
	private ITileFilePathCreator dstCreator;
	
	private GoogleTileParser googleTileParser;
	private GoogleTileFileHook googleTileFileHook;
	private boolean isInit=false;
	private List<AbstractObjectCycleThread> threadList=new ArrayList<AbstractObjectCycleThread>();
	private AbstractQuickSleepFirstThread checkThread;
	private WaitMessageQueue waitMessageQueue=new WaitMessageQueue();
	
	public GoogleTileFileParser(GoogleTileParser googleTileParser){
		this.googleTileParser=googleTileParser;
	}

	public void setMapConfig(MapConfig mapConfig) {
		this.mapConfig = mapConfig;
	}

	
	/**
	 * 初始化线程
	 * @throws Exception
	 */
	public void init() throws Exception{
		for(int i=0;i<mapConfig.getThreadNum();i++){
			AbstractObjectCycleThread oct=new AbstractObjectCycleThread(){
				@Override
				protected void process(IMessage result) {
					TileWrapperMessage tw=(TileWrapperMessage)result;
					TileWrapper gtw=tw.getTileWrapper();
					//源目标文件夹
					FileWrapper srcFileWp=srcCreator.createWrapper(mapConfig.getSrcFilePath(), gtw);
					//目标文件夹
					FileWrapper dstFileWp=dstCreator.createWrapper(mapConfig.getDstFilePath(), gtw);
					
					googleTileFileHook.hook(tw.getIndex()+1, tw.getTotal(), srcFileWp,dstFileWp, gtw);
				}
			};
			oct.setName("ParseThread_"+i);
			oct.setWaitMessageQueue(waitMessageQueue);
			oct.init();
			oct.start();
			threadList.add(oct);
		}
		
		//检查线程，检查地图是否已经下载完成
		checkThread=new AbstractQuickSleepFirstThread() {
			@Override
			protected void handle() throws Exception {
				if(googleTileParser.isParseOver()){
					if(waitMessageQueue.size() == 0){
						mapConfig.display("检测到地图已经切片完成，准备关闭所有线程");
						for(AbstractObjectCycleThread oc:threadList){
							oc.shutdown();
							mapConfig.display("关闭线程【"+oc.getName()+"】");
						}
						
						AbstractQuickSleepFirstThread thread=googleTileParser.getSavePropertiesThread();
						thread.shutdown();
						mapConfig.display("关闭线程【"+thread.getName()+"】");
						
						//关闭当前线程
						checkThread.shutdown();
						mapConfig.display("关闭线程【"+checkThread.getName()+"】");
						mapConfig.display("任务结束,所有线程已经关闭");
					}
				}
				
			}
		};
		checkThread.setSleepTime(TimeUtil.SECOND_MILLI*10);
		checkThread.setName("CheckThread");
		checkThread.init();
		checkThread.start();
	}
	
	
	/**
	 * 开始解析
	 */
	public void doParse(){
		googleTileParser.setGoogleTileHooker(new GoogleTileHooker(){
			@Override
			public void hook(long totalNum,int curNum,TileWrapper googleTileWrapper) {
				TileWrapperMessage twm=new TileWrapperMessage();
				twm.setIndex(curNum);
				twm.setTotal(totalNum);
				twm.setTileWrapper(googleTileWrapper);
				waitMessageQueue.addMessage(twm);
				while(waitMessageQueue.size()>6000){
					try {
						Thread.sleep(TimeUtil.SECOND_MILLI*3);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		});
		googleTileParser.doParse();
		
		clear();
	}
	
	/**
	 * 清除数据
	 */
	private void clear(){
		isInit=false;
	}
	
	
	/**
	 * 将瓦片解析成文件信息
	 * @author lcb
	 */
	public static interface GoogleTileFileHook{
		void hook(int index,long total,FileWrapper srcFileWp,FileWrapper dstFileWp,TileWrapper googleTileWrapper);
	}
	

	public void setGoogleTileFileHook(GoogleTileFileHook googleTileFileHook) {
		this.googleTileFileHook = googleTileFileHook;
	}

	public void setSrcCreator(ITileFilePathCreator srcCreator) {
		this.srcCreator = srcCreator;
	}

	public void setDstCreator(ITileFilePathCreator dstCreator) {
		this.dstCreator = dstCreator;
	}
	
}
